package com.zhiyin.seal.websocket;

import com.alibaba.fastjson.JSON;
import com.zhiyin.seal.entity.dto.WebSocketRequestDTO;
import com.zhiyin.seal.entity.vo.WebSocketMessageVo;
import com.zhiyin.seal.service.ApplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/websocket")
@Component
public class WebsocketServer {

    // 静态注入方式
    static ApplyService applyService;

    @Autowired
    public void setApplyService(ApplyService applyService){
        WebsocketServer.applyService = applyService;
    }

    /**
     * 存放所有在线的客户端
     */
    private static Map<String, Session> clients = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session) {
        // 从请求中获取userId
        Map<String, List<String>> requestParameterMap = session.getRequestParameterMap();
        List<String> paramsList = requestParameterMap.get("userId");
        // 如果id为空，直接关闭socket
        if(paramsList == null){
            try {
                session.close();
            } catch (IOException e) {

            }
            return;
        }
        String userId = paramsList.get(0);
        // 判断是否之前已经存在，如果存在且是连接状态则关闭并移除
        Session oldSession = clients.get(userId);
        if(oldSession != null){
            try {
                if(oldSession.isOpen()){
                    // 关闭
                    oldSession.close();
                }
                // 移除
                clients.remove(userId);
            } catch (IOException e) {

            }
        }
        //将新用户存入在线的组
        clients.put(userId, session);
    }

    /**
     * 客户端关闭
     * @param session session
     */
    @OnClose
    public void onClose(Session session) {
        // 从请求中获取userId
        Map<String, List<String>> requestParameterMap = session.getRequestParameterMap();
        List<String> paramsList = requestParameterMap.get("userId");
        if(paramsList != null && paramsList.size() > 0){
            String userId = paramsList.get(0);
            //将掉线的用户从clients集合中移除
            clients.remove(userId);
            try{
                session.close();
            } catch (IOException ex){

            }
        }
    }

    /**
     * 发生错误
     * @param throwable e
     */
    @OnError
    public void onError(Throwable throwable) {
    }

    /**
     * 收到客户端发来消息
     * @param message  消息对象
     */
    @OnMessage
    public void onMessage(String message) {
        WebSocketRequestDTO requestDTO = JSON.parseObject(message,WebSocketRequestDTO.class);
        Long userId = requestDTO.getUserId();
        String operateType = requestDTO.getOperateType();
        // 获取是否有审批状态
        if(WebSocketRequestDTO.WAIT_APPROVAL.equals(operateType)){
            Boolean result = applyService.getHasMyApproval(userId);
            WebSocketMessageVo messageVo = new WebSocketMessageVo();
            messageVo.setOperateType(WebSocketRequestDTO.WAIT_APPROVAL);
            messageVo.setHasApproval(result);
            sendDataByUserId(userId.toString(),messageVo);
        }
        // 获取是否有可用单据
        if(WebSocketRequestDTO.AVAILABLE_APPLY.equals(operateType)){
            Boolean result = applyService.getHasMyAvailableApply(userId);
            WebSocketMessageVo messageVo = new WebSocketMessageVo();
            messageVo.setOperateType(WebSocketRequestDTO.AVAILABLE_APPLY);
            messageVo.setAvailableApply(result);
            sendDataByUserId(userId.toString(),messageVo);
        }
    }

    /**
     * 给用户发送消息
     * @param userId
     * @param messageVo
     */
    public static void sendDataByUserId(String userId, WebSocketMessageVo messageVo){
        Session session = clients.get(userId);
        if(session != null){
            if(session.isOpen()){
                try{
                    session.getAsyncRemote().sendText(JSON.toJSONString(messageVo));
                } catch (Exception ex){
                    clients.remove(userId);
                }
            }
        }
    }
}
